package settings

import (
	"fmt"

	"github.com/fsnotify/fsnotify"

	"github.com/spf13/viper"
)

var Conf = new(AppConfig)

type AppConfig struct {
	Name            string `mapstructure:"name"`
	Mode            string `mapstructure:"mode"`
	Version         string `mapstructure:"version"`
	Type            string `mapstructure:"type"`
	Addr            string `mapstructure:"addr"`
	Port            int    `mapstructure:"port"`
	*LogConfig      `mapstructure:"log"`
	*FilePathConfig `mapstructure:"file"`
}

type LogConfig struct {
	Level      string `mapstructure:"level"`
	Filename   string `mapstructure:"filename"`
	MaxSize    int    `mapstructure:"max_size"`
	MaxAge     int    `mapstructure:"max_age"`
	MaxBackups int    `mapstructure:"max_backups"`
}

type FilePathConfig struct {
	ReadFileName  string `mapstructure:"read"`
	WidteFileName string `mapstructure:"write"`
}

func Init(filepath string) (err error) {
	// 方式1:直接指定配置文件路径（相对路径或者绝对路径）
	// 相对路径：相对执行的可执行文件相对路径
	// 绝对路径：系统中实际的文件路径
	//viper.SetConfigFile("./conf/config.yaml")
	// 方式2：指定配置文件名和配置文件的位置，viper自行查找可用的配置文件
	// 配置文件名不需要带后缀
	// 配置文件位置可配置多个
	//viper.SetConfigName("config") // 指定配置文件名称（不需要带后缀）
	//viper.AddConfigPath("./conf")  // 指定查找配置文件的路径（这里使用相对路径）
	//viper.SetConfigType("yaml")   // 指定配置文件类型（专用于从远程获取配置信息时指定配置文件的类型）
	//viper.SetConfigType("json")   // 指定配置文件类型（专用于从远程获取配置信息时指定配置文件的类型）
	//viper.AddConfigPath(".")   // 指定查找配置文件的路径（这里使用相对路径）

	viper.SetConfigFile(filepath)

	err = viper.ReadInConfig() // 读取配置文件
	if err != nil {
		fmt.Printf("viper.ReadInConfig() failed, err:%v\n", err)
		return
	}
	// 把读取到的配置信息反序列化到 Conf 变量中
	if err := viper.Unmarshal(Conf); err != nil {
		fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
	}

	viper.WatchConfig()
	// 监听配置文件变化
	viper.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("config file change..")
		// 配置文件改变 重新反序列化到 Conf
		if err := viper.Unmarshal(Conf); err != nil {
			fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
		}
	})
	return
}
